package com.ccteam.fluidmusic.ui.local.tag

import android.app.Application
import android.net.Uri
import androidx.lifecycle.*
import com.ccteam.fluidmusic.core.TaglibParser
import com.ccteam.fluidmusic.utils.Event
import com.ccteam.fluidmusic.utils.setValueIfNew
import com.ccteam.fluidmusic.view.bean.ErrorMessage
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.network.ApiError
import com.ccteam.taglib.core.MediaTag
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.FileNotFoundException
import java.io.IOException
import javax.inject.Inject

/**
 * @author Xiaoc
 * @since 2021/4/9
 *
 * 本地音乐标签显示修改ViewModel
 */
@HiltViewModel
class LocalMusicTagViewModel @Inject constructor(
    private val taglibParser: TaglibParser,
    savedStateHandle: SavedStateHandle,
    application: Application
): AndroidViewModel(application) {

    val mediaUri = MutableLiveData<Uri>()

    private val _mediaTagInfo = MediatorLiveData<MediaTag>()
    val mediaTagInfo: LiveData<MediaTag> get() = _mediaTagInfo

    private val _editLoadMessage = MutableLiveData<Event<LoadMessage>>()
    val editLoadMessage: LiveData<Event<LoadMessage>> get() = _editLoadMessage

    init {
        _mediaTagInfo.addSource(mediaUri){
            getMediaTag()
        }

        mediaUri.setValueIfNew(savedStateHandle["mediaUri"])
    }

    /**
     * 设置媒体标签内容
     * 接受基本通用的媒体标签项，将其打包为 MediaTag 类后传递到native层
     *
     * @param title 标题
     * @param track 音轨
     * @param year 年份
     * @param genre 流派
     * @param artist 艺术家
     * @param composer 作曲家
     * @param album 专辑
     * @param comment 注释
     * @param albumArtist 专辑艺术家
     * @param copyright 版权
     */
    fun setMediaTag(
        title: String,track: String,year: String,
        genre: String,artist: String,composer: String,
        album: String,comment: String,albumArtist: String,
        copyright: String
    ){
        _editLoadMessage.value = Event(LoadMessage.Loading)

        val mediaTag = MediaTag().apply {
            this.title = title
            this.track = track.toInt()
            this.year = year.toInt()
            this.genre = genre
            this.artist = artist
            this.composer = composer
            this.album = album
            this.comment = comment
            this.albumArtist = albumArtist
            this.copyright = copyright
        }

        mediaUri.value?.let { uri ->
            createEditableRequest(mediaTag,uri)
        }
    }

    private fun createEditableRequest(mediaTag: MediaTag, uri: Uri){
        val application = getApplication<Application>()

        viewModelScope.launch(Dispatchers.IO) {
            try {
                application.contentResolver.openFileDescriptor(uri,"rw")?.use {
                    if(setMediaTagByNative(
                            mediaTag,it.detachFd()
                        )){
                        _editLoadMessage.postValue(Event(LoadMessage.Success))
                    } else {
                        _editLoadMessage.postValue(Event(LoadMessage.Error(ErrorMessage("修改失败",ApiError.unknownCode))))
                    }
                }
            } catch (e: IOException){
                _editLoadMessage.value = Event(LoadMessage.Error(ErrorMessage("修改失败",ApiError.unknownCode)))
            }
        }
    }

    private suspend fun setMediaTagByNative(mediaTag: MediaTag,fd: Int): Boolean{
        return taglibParser.setMediaTag(mediaTag,fd)
    }

    private fun getMediaTag(){
        mediaUri.value?.let { uri ->
            val application = getApplication<Application>()
            viewModelScope.launch(Dispatchers.IO) {
                try {
                    application.contentResolver.openFileDescriptor(uri,"r")?.use {
                        _mediaTagInfo.postValue(taglibParser.getMediaTag(it.detachFd()))
                    }
                } catch (e: FileNotFoundException){ }
            }
        }

    }
}